// async_robot.cpp: 定义控制台应用程序的入口点。
//
#include "logic.h"
#include <boost/thread.hpp>
#ifdef WIN32

#else
#include <unistd.h>
#endif

using namespace std;

vector<string> split(const string& str, string pattern)
{
	vector<string> ret;
	if (pattern.empty()) return ret;
	size_t start = 0, index = str.find_first_of(pattern, 0);
	while (index != str.npos)
	{
		if (start != index)
			ret.push_back(str.substr(start, index - start));
		start = index + 1;
		index = str.find_first_of(pattern, start);
	}
	if (!str.substr(start).empty())
		ret.push_back(str.substr(start));
	return ret;
}

class client
{
public:
	client(boost::asio::io_service& io_context, string ip, short port, int id, RobotRule rule)
	{
		ses = std::make_shared<LogicTask>(io_context,id,ip,port, rule);
		ses->start();
	}
	~client()
	{
	}
	shared_ptr<LogicTask> ses;
};

int main(int argc, char* argv[])
{
// 	Json::Value val;
// 	Json::Reader reader;
// 	string str = "{\"form_mjs\":1}";
// 	if (reader.parse(str, val) < 0)
// 	{
// 		printf("recvData: [%s]\n", str.c_str());
// 		return -1;
// 	}
// 	if (val.isNull())
// 	{
// 		printf("isNull: [%s]\n", str.c_str());
// 	}
// 	if (val.isObject())
// 	{
// 		printf("isObject: [%s]\n", str.c_str());
// 	}
// 	printf("recvDataStyled: [%s]\n", val.toStyledString().c_str());
// 	return 0;
	boost::asio::io_service io_service;
	try
	{
		if (argc != 2)
		{
			std::cout << "Usage: yxj_robot <conf_file>\n";
			return 1;
		}

		//boost::asio::io_context io_context;
		std::ifstream conf(argv[1], std::ifstream::binary);
		if (!conf)
		{
			std::cout << "init file no found." << endl;
			return 1;
		}

		Json::Reader reader;
		Json::Value root;
		bool ret = reader.parse(conf, root);
		if (!ret) {
			conf.close();
			std::cout << "init file parser." << endl;
			return false;
		}
		int begin(root["begin"].asInt());
		int end(root["end"].asInt());
		string ip(root["ip"].asString());
		int port(root["port"].asInt());
		LogicTask::url = (root["env"].asString());
		RobotRule rule;
// 		rule._max_gang_sec = root["max_gang_sec"].asInt();
// 		rule._min_gang_sec = root["min_gang_sec"].asInt();
// 		rule._max_peng_sec = root["max_peng_sec"].asInt();
// 		rule._min_peng_sec = root["min_peng_sec"].asInt();
// 		rule._max_hu_sec = root["max_hu_sec"].asInt();
// 		rule._min_hu_sec = root["min_hu_sec"].asInt();
// 		rule._max_sec = root["max_sec"].asInt();
// 		rule._min_sec = root["min_sec"].asInt();
		auto decode_time = [](map<int, int>& map_, const Json::Value& val)
		{
			string str = val.asString();
			auto vec = split(str, ";");
			for (auto& info : vec)
			{
				auto vec2 = split(info, ",");
				if (vec2.size() == 2)
				{
					map_[atoi(vec2[0].c_str())] = atoi(vec2[1].c_str());
				}
			}
			for (auto& info : map_)
			{
				cout << "first:" << info.first << " second:" << info.second << endl;
			}
		};
		decode_time(rule._out_time, root["out_time"]);
		decode_time(rule._hu_time, root["hu_time"]);
		decode_time(rule._peng_time, root["peng_time"]);
		decode_time(rule._gang_time, root["gang_time"]);
		conf.close();

		// 增加一个work对象  
		boost::asio::io_service::work work(io_service);
		cout << "begin" << endl;
		vector<shared_ptr<client>> vec_cli;
		vector<boost::shared_ptr<boost::thread>> threads;
		for (int i(0); i < 20; i++)
		{
			cout << "new thread" << endl;
			boost::shared_ptr<boost::thread> _thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service)));
			threads.push_back(_thread);
		}
		SpinLock lock;
		boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(20));
		typedef std::function<void(const boost::system::error_code&)> timer_callback;
		timer_callback callback = [&](const boost::system::error_code& err)
		{
			SmartLock<SpinLock> smart(lock);
			int no_heat_people(0);
			int heat_people(0);
			int total_proto(0);
			int total_broad(0);
			cout << "user count:" << vec_cli.size() << endl;
			for (auto cli : vec_cli)
			{
				auto logic = cli->ses;
				if (logic->proto_cnt == 0)
				{
					no_heat_people++;
				}
				else {
					heat_people++;
				}
				total_proto += logic->proto_cnt;
				total_broad += logic->board_cnt;
				logic->init();
				cli->ses->ping();
			}
			cout << "cur_time:" << time(NULL) << endl;
			cout << "no_heat_people:" << no_heat_people << endl;
			cout << "heat_people:" << heat_people << endl;
			cout << "total_proto:" << total_proto << endl;
			cout << "total_broad:" << total_broad << endl << endl;;
			timer.expires_at(timer.expires_at() + boost::posix_time::seconds(20));
			timer.async_wait(callback);
		};
		timer.async_wait(callback);
		boost::asio::deadline_timer timer2(io_service, boost::posix_time::seconds(10));
		typedef std::function<void(const boost::system::error_code&)> timer_callback;
		timer_callback callback2 = [&](const boost::system::error_code& err)
		{
			int rand = LogicTask::random(0, vec_cli.size());
			while (1)
			{
				for (auto cli : vec_cli)
				{
					auto logic = cli->ses;
					if (logic->_on_seat == false)
					{
						if (rand == 0)
						{
							logic->join_room_req();
							break;
						}
						else rand--;
					}
				}
				if (rand == 0)
				{
					break;
				}
			}
			timer2.expires_at(timer2.expires_at() + boost::posix_time::seconds(1));
			timer2.async_wait(callback2);
		};

		boost::shared_ptr<boost::thread> _thread(new boost::thread(
			[&]()
		{
			for (int i(begin); i <= end; i++)
			{
				SmartLock<SpinLock> smart(lock);
#ifdef WIN32
				Sleep(10);
#else
				usleep(10);
#endif
				auto s = make_shared<client>(io_service, ip, port, i, rule);
				vec_cli.push_back(s);
			}
			cout << "over" << endl;
			timer2.async_wait(callback2);
		}));
// 		for (int i(begin); i <= end; i++)
// 		{
// 			Sleep(10);
// 			auto s = make_shared<client>(io_service, ip, port, i, rule);
// 			vec_cli.push_back(s);
// 		}
// 		cout << "over" << endl;
// 		timer2.async_wait(callback2);
// 		io_service.run();
		for (auto& it : threads)
		{
			it->join();
			cout << "kill " << it->get_id() << endl;
		}
		cout << "end" << endl;
	}
	catch (std::exception& e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
	}
	return 0;
}